package wait

import (
	"sync"
	"time"
)

/**
 * @Author: hejing@szlabsun.com
 * @Description: 让线程等待的工具类 对sync.WaitGroup的封装
 * WaitGroup 对象内部有一个计数器，最初从0开始，它有三个方法：Add(), Done(), Wait() 用来控制计数器的数量。
 * Add(n) 把计数器设置为n ，Done() 每次把计数器-1 ，wait() 会阻塞代码的运行，直到计数器地值减为0
 * @File:  waitUtil
 * @Version: 1.0.0
 * @Date: 2021/7/23 11:01
 */
// Wait is similar with sync.WaitGroup which can wait with timeout
type Wait struct {
	wg sync.WaitGroup
}

// Add adds delta, which may be negative, to the WaitGroup counter.
func (w *Wait) Add(delta int) {
	w.wg.Add(delta)
}

// Done decrements the WaitGroup counter by one
func (w *Wait) Done() {
	w.wg.Done()
}

// Wait blocks until the WaitGroup counter is zero.
func (w *Wait) Wait() {
	w.wg.Wait()
}

// 任务正常完成则返回false  等待时间超过timeout则返回false
func (w *Wait) WaitWithTimeout(timeout time.Duration) bool {
	c := make(chan bool)
	go func() {
		defer close(c)
		w.wg.Wait()
		c <- true //当任务正常完成 向通道写入
	}()
	select {
	case <-c:
		return false // completed normally 任务正常完成
	case <-time.After(timeout):
		return true // timed out
	}
}
